﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.IO;
using System.Web.Mvc;
using YeaTrip.Common;
using System.Xml;

namespace YeaTrip.Framework.Log
{
    public enum LogType
    {
        TransLog,
        ErrorLog,
        SysLog
    }
    public class YeaTripLog
    {
        private static StringBuilder[] logStrings = null;
        private static string _webPath = string.Empty;
        private static Timer logTimer = null;

        public static void Init(string webPath)
        {
            _webPath = webPath;
            logStrings = new StringBuilder[3] { new StringBuilder(), new StringBuilder(), new StringBuilder() };

            logTimer = new Timer();
            logTimer.AutoReset = true;
            //配置文件中的单位是秒
            logTimer.Interval = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["LogTimerSpan"]) * 1000;
            if (logTimer.Interval == 0)
            {
                logTimer.Interval = 10000;
            }
            logTimer.Elapsed += new ElapsedEventHandler(Write);

            LogInfo("网站启动");
            logTimer.Start();
        }

        /// <summary>
        /// 记录错误信息日志
        /// </summary>
        /// <param name="error">错误信息</param>
        public static void LogError(string error)
        {
            PushLog(error, LogType.ErrorLog);
        }

        /// <summary>
        /// 记录提示信息日志
        /// </summary>
        /// <param name="msg">提示消息</param>
        public static void LogInfo(string msg)
        {
            PushLog(msg, LogType.SysLog);
        }

        /// <summary>
        /// 记录异常日志
        /// </summary>
        /// <param name="ex">异常</param>
        public static void LogException(Exception ex)
        {
            string exceptionMsg = "未知错误";
            string exceptionStackTrace = "未知StackTrace";
            if (ex != null)
            {
                if (!string.IsNullOrEmpty(ex.Message))
                {
                    exceptionMsg = ex.Message;
                }
                if (!string.IsNullOrEmpty(ex.StackTrace))
                {
                    exceptionStackTrace = ex.StackTrace;
                }
            }
            string logContext = exceptionMsg + "\r\n" + exceptionStackTrace;
            PushLog(logContext, LogType.ErrorLog);
        }

        /// <summary>
        /// 记录Transaction日志
        /// </summary>
        /// <param name="filterContext"></param>
        public static void LogTrans(ControllerContext filterContext)
        {
            string action = filterContext.RouteData.Values["controller"].ToString() + "/" + filterContext.RouteData.Values["action"].ToString();
            string ip = filterContext.HttpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            string sessionID = filterContext.HttpContext.Session.SessionID;
            string reqParams = string.Empty;
            foreach (var item in ((ActionExecutingContext)filterContext).ActionParameters)
            {
                if (!item.Value.GetType().Equals(typeof(System.Web.Mvc.FormCollection)))
                {
                    reqParams += XmlSerializeHelper.XmlSerialize(item.Value);
                }
            }

            StringBuilder sb = new StringBuilder(2048);
            StringWriter sw = new StringWriter(sb);
            XmlTextWriter xtw = new XmlTextWriter(sw);
            xtw.Formatting = Formatting.Indented;

            xtw.WriteStartElement("transDataLog");
            xtw.WriteAttributeString("time", DateTime.Now.ToLongTimeString());
            xtw.WriteAttributeString("sessionID", sessionID);
            xtw.WriteAttributeString("actionName", action);
            xtw.WriteAttributeString("ip", ip);

            xtw.WriteStartElement("reqXml");
            xtw.WriteRaw(reqParams);
            xtw.WriteEndElement();


            xtw.WriteEndElement();

            xtw.Flush();
            xtw.Close();

            PushLog(sb.ToString(), LogType.TransLog);
        }

        /// <summary>
        /// 将log装载入日志数组
        /// </summary>
        /// <param name="logContent"></param>
        /// <param name="logType"></param>
        private static void PushLog(string logContent, LogType logType)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(string.Format("[{0:HH}:{0:mm}:{0:ss}:{0:fff}]", DateTime.Now));
            sb.Append("[" + logType.ToString() + "]");
            sb.Append(logContent);
            sb.Append("\r\n");

            logStrings[(int)logType].Append(sb.ToString());
        }

        /// <summary>
        /// 将日志写入文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void Write(object sender, ElapsedEventArgs e)
        {
            for (int i = 0; i < logStrings.Length; i++)
            {
                string path = _webPath + "\\Logs\\" + Enum.GetName(typeof(LogType), i);
                string fileName = string.Format("{0:yyyy}{0:MM}{0:dd}.log", DateTime.Now);
                try
                {
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }
                    if (logStrings[i].Length > 0)
                    {
                        File.AppendAllText(path + "\\" + fileName, logStrings[i].ToString());
                    }
                }
                catch
                {
                }
                finally
                {
                    logStrings[i].Clear();
                }
            }
        }
    }
}
